import json
import os

from lucommon.logger import lu_logger

from cert.service import gen_ca_config, gen_ca_csr_config, sign_ca, \
    gen_cert_csr_config, sign_cert, \
    get_cert_info, \
    gen_kube_config_by_cert, gen_kube_config_by_token, set_default_context
from utils import gen_static_dir, download_file, gen_tmp_file_path


def gen_ca_cert(params):
    ca_info = params.get("ca", {})
    certs_info = params.get("certs", [])  # todo 请求参数标准化

    data = {}  # 结果

    # 生成证书存放目录
    static_dir = gen_static_dir()
    config_dir = "{}/conf".format(static_dir)
    cert_dir = "{}/cert".format(static_dir)
    os.mkdir(config_dir)
    os.mkdir(cert_dir)
    lu_logger.debug("conf dir:{}".format(config_dir))
    lu_logger.debug("cert dir:{}".format(cert_dir))
    data["conf"] = {}
    data["cert"] = {}

    # 签发ca
    profiles = ca_info["profiles"]
    ca_expiry = ca_info["expiry"]
    ca_CN = ca_info["CN"]
    ca_config = gen_ca_config(config_dir, profiles)
    ca_csr_config = gen_ca_csr_config(config_dir, ca_CN, ca_expiry)
    data["conf"]["ca-config"] = ca_config
    data["conf"]["ca-csr-config"] = ca_csr_config
    lu_logger.debug("ca-config:{}".format(ca_config))
    lu_logger.debug("ca-csr-config:{}".format(ca_csr_config))

    c, _, err, (ca_path, ca_key_path, ca_csr_path) = sign_ca(cert_dir, ca_csr_config)
    if c != 0:
        lu_logger.error("ca签发失败,err:{}".format(err))
        return {}, err
    data["cert"]["ca"] = ca_path
    data["cert"]["ca-key"] = ca_key_path
    data["cert"]["ca-csr"] = ca_csr_path
    lu_logger.debug("ca_path:{}".format(ca_path))
    lu_logger.debug("ca_key_path:{}".format(ca_key_path))
    lu_logger.debug("ca_csr_path:{}".format(ca_csr_path))
    lu_logger.info("ca签发成功")

    # 签发证书
    cert_csr_config_map = gen_cert_csr_config(config_dir, certs_info)
    data["conf"].update({
        "{}-csr-config".format(name): conf
        for name, (_, conf) in cert_csr_config_map.items()
    })
    for name, (profile, cert_csr_config) in cert_csr_config_map.items():
        c, _, err, (cert, cert_key, cert_csr) = sign_cert(
            ca_path=ca_path,
            ca_key_path=ca_key_path,
            ca_config_path=ca_config,
            profile=profile,
            cert_csr_config=cert_csr_config,
            cert_name=name,
            cert_dir=cert_dir,
        )
        if c != 0:
            lu_logger.error("{} cert签发失败,err:{}".format(name, err))
            return {}, err
        data["cert"]["{}".format(name)] = cert
        data["cert"]["{}-key".format(name)] = cert_key
        data["cert"]["{}-csr".format(name)] = cert_csr
        lu_logger.debug("{}_path:{}".format(name, ca_path))
        lu_logger.debug("{}_key_path:{}".format(name, cert_key))
        lu_logger.debug("{}_csr_path:{}".format(name, cert_csr))
        lu_logger.info("{} cert签发成功".format(name))

    lu_logger.debug("ca-cert-data:{}".format(data))

    return data, ""


def cert_info(params):
    cert_link = params.get("cert-link", "")
    tmp_cert = gen_tmp_file_path()
    download_file(cert_link, tmp_cert)
    c, stdout, stderr = get_cert_info(tmp_cert)
    os.remove(path=tmp_cert)
    if c != 0:
        lu_logger.error("cert info 获取失败,err:{}".format(stderr))
        return {}, stderr

    return json.loads(stdout), ""


def gen_kubeconfig(params):
    default_context = params["default_context"]
    config_name = params["config_name"]
    clusters = params["clusters"]

    lu_logger.debug("gen-kubeconfig {}".format(config_name))
    lu_logger.debug("clusters info:{}".format(clusters))

    # 生成config存放目录
    static_dir = gen_static_dir()
    config_dir = "{}/kubeconfig".format(static_dir)
    os.mkdir(config_dir)
    lu_logger.debug("kubeconfig dir:{}".format(config_dir))

    kubeconfig_path = "{}/{}".format(config_dir, config_name)

    for cluster in clusters:
        """
        每个集群配置中，先查找token，如果存在token，则使用token生成kubeconfig
        然后再查找cert和key，通过证书生成kubeconfig
        """
        ca = cluster.get("ca")
        if not ca:
            return "", "未指定ca"
        ca_file = download_file(ca, gen_tmp_file_path()) if "http" in ca else ca
        token = cluster.get("token")
        if token:
            # 用token生成kubeconfig
            c, stdout, stderr = gen_kube_config_by_token(
                cluster=cluster["cluster"],
                apiserver=cluster["apiserver"],
                user=cluster["user"],
                context=cluster["context"],
                kube_config_path=kubeconfig_path,
                ca=ca_file,
                token=token
            )
            if c != 0:
                return "", stderr
            continue
        cert, cert_key = cluster.get("cert"), cluster.get("cert_key")
        if not all([cert, cert_key]):
            return "", "未指定证书"

        cert_file = download_file(cert, gen_tmp_file_path()) if "http" in cert else cert
        cert_key_file = download_file(cert_key, gen_tmp_file_path()) if "http" in cert_key else cert_key
        c, stdout, stderr = gen_kube_config_by_cert(
            cluster=cluster["cluster"],
            apiserver=cluster["apiserver"],
            user=cluster["user"],
            context=cluster["context"],
            kube_config_path=kubeconfig_path,
            ca=ca_file,
            cert=cert_file,
            cert_key=cert_key_file
        )
        if c != 0:
            return "", stderr

    c, stdout, stderr = set_default_context(kubeconfig_path, default_context)
    if c != 0:
        return "", stderr

    lu_logger.debug("gen-kubeconfig success:{}".format(kubeconfig_path))

    return kubeconfig_path, ""
